package project.batch.generic.csv;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.nio.charset.Charset;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;

import project.batch.JdbcQuery;
import project.common.CsvUtil;

import common.db.JdbcSource;

import core.util.MojiUtil;

/**
 * 汎用CSV一括出力クエリ実行
 * @author Tadashi Nakayama
 */
public final class ExtractBatchQuery extends JdbcQuery {

	/** 出力ストリーム */
	private OutputStream os = null;
	/** クエリ */
	private String query = null;
	/** タイトル */
	private byte[] title = null;
	/** Charset */
	private Charset charset = JdbcSource.getCharset();
	/** 処理結果 */
	private boolean result;

	/**
	 * 出力ストリーム設定
	 * @param val 出力ストリーム
	 */
	public void setOutputStream(final OutputStream val) {
		this.os = val;
	}

	/**
	 * クエリ設定
	 * @param val クエリ
	 */
	public void setQuery(final String val) {
		this.query = val;
	}

	/**
	 * タイトル設定
	 * @param val タイトル
	 */
	public void setTitle(final String... val) {
		this.title = CsvUtil.toByteTitle(val, this.charset);
	}

	/**
	 * Charset設定
	 * @param val Charset
	 */
	public void setCharset(final Charset val) {
		this.charset = val;
	}

	/**
	 * 処理結果取得
	 * @return 処理した場合 true を返す。
	 */
	public boolean getResult() {
		return this.result;
	}

	/**
	 * @see common.sql.SelectQuery#callback(java.sql.ResultSet)
	 */
	@Override
	public boolean callback(final ResultSet rs) throws SQLException {
		ResultSetMetaData rsmd = rs.getMetaData();

		try {
			if (this.title != null && 0 < this.title.length) {
				this.os.write(this.title);
			}

			this.result = false;
			byte[] crlf = CsvUtil.crlf(this.charset);
			byte[] comm = CsvUtil.comma(this.charset);
			while (rs.next()) {
				this.result = true;
				this.os.write(toBytes(rs.getString(1)));
				for (int i = 2; i <= rsmd.getColumnCount(); i++) {
					this.os.write(comm);
					this.os.write(toBytes(rs.getString(i)));
				}
				this.os.write(crlf);
			}

			return this.result;
		} catch (final IOException ex) {
			throw new UncheckedIOException(ex);
		}
	}

	/**
	 * バイト化
	 * @param val 文字列
	 * @return バイト化文字列
	 */
	private byte[] toBytes(final String val) {
		return MojiUtil.correctGarbled(
				CsvUtil.toCsvValue(val), this.charset).getBytes(this.charset);
	}

	/**
	 * @see common.sql.SelectQuery#makeQuery()
	 */
	@Override
	public String makeQuery() {
		return this.query;
	}
}
